package org.zoomdev.zoom.aop.utils;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.*;

public class CopyMethodVisitor extends ClassVisitor {

    private final String className;

    private final String oldNew;

    private final String replaceNew;

    private final String methodName;

    public CopyMethodVisitor(ClassVisitor classVisitor, String className, String methodName, String oldNew, String replaceNew) {
        super(ASM9, classVisitor);
        this.className = className;
        this.oldNew = oldNew;
        this.replaceNew = replaceNew;
        this.methodName = methodName;
    }


    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, className, signature, superName, interfaces);
    }


    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        //System.out.println("visit method:" + name + "====> " + descriptor);

        if (name.equals("<init>")) {
            return super.visitMethod(access, name, descriptor, signature, exceptions);
        }

        if (!methodName.equals(name)) {
            return null;
        }

        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        return new MethodVisitor(Opcodes.ASM9, mv) {

            @Override
            public void visitTypeInsn(int opcode, String type) {
                if (opcode == NEW) {
                    if (type.equals(oldNew)) {
                        type = replaceNew;
                    }
                }
                super.visitTypeInsn(opcode, type);
            }


            @Override
            public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
                if (opcode == GETFIELD) {
                    owner = className;
                }
                super.visitFieldInsn(opcode, owner, name, descriptor);
            }

            @Override
            public void visitMethodInsn(int opcode, String owner, String name,
                                        String descriptor, boolean isInterface) {
                if (opcode == Opcodes.INVOKESPECIAL && owner.equals(oldNew)) {
                    owner = replaceNew;
                }
                super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
            }
        };
    }


    @Override
    public void visitEnd() {
//                //特别注意的是：要为类增加属性和方法，放到visitEnd中，避免破坏之前已经排列好的类结构，在结尾添加新结构
//                //增加一个字段（注意不能重复）,注意最后都要visitEnd
//                FieldVisitor fv = cv.visitField(ACC_PUBLIC, "phone", "Ljava/lang/String;", null, null);
//                fv.visitEnd();//不能缺少visitEnd
//
//                //增加一个方法
//                MethodVisitor mv=cv.visitMethod(ACC_PUBLIC,"getPhone","()Ljava/lang/String;",null,null);
//                mv.visitCode();
//                mv.visitVarInsn(ALOAD, 0);
//                mv.visitFieldInsn(GETFIELD,"com/test/javase_module/TestFunction","phone","Ljava/lang/String;");
//                mv.visitInsn(IRETURN);
//                mv.visitMaxs(1, 1);
//                mv.visitEnd();//不能缺少visitEnd
        super.visitEnd();//注意原本的visiEnd不能少
    }

}